//条件变量pthread_cond_wait作用：1.释放该线程的锁，2.将该线程放入等待锁资源的队列中，当有锁可用，且轮到自己获取锁的时候就将其拿出来




// 操作变量共享会有问题的售票系统

#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <cstdio>
#include <mutex>

using std::cin;
using std::cout;
using std::endl;
using std::to_string;
using std::string;

const int Num = 5; // 线程个数
int ticket = 1000;  // 临界资源、共享资源


// typedef void(*func_t)(const string name,pthread_mutex_t* pmutex,pthread_cond_t* pcond);
typedef void(*func_t)();




class ThreadData
{
public:
    ThreadData(string name,pthread_mutex_t* pmutex,pthread_cond_t* pcond,func_t func) : _name(name),_pmutex(pmutex),_pcond(pcond),_func(func)
    {
    }
    ~ThreadData()
    {
    }

public:
    string _name;
    pthread_mutex_t* _pmutex;
    pthread_cond_t* _pcond;
    func_t _func;
};

//售卖机
void func1()
{
    cout<<"人脸识别 running----"<<endl;
}

void func2()
{
    cout<<"选择商品 running----"<<endl;
}

void func3()
{
    cout<<"查询商品库存 running----"<<endl;
}

void func4()
{
    cout<<"取出商品 running----"<<endl;
}

void func5()
{
    cout<<"付款成功 running----"<<endl;
}

void* Entry(void* arg)
{
    pthread_detach(pthread_self());
    ThreadData* tdata=(ThreadData*)arg;
    while(true)
    {
        pthread_mutex_lock(tdata->_pmutex);
        pthread_cond_wait(tdata->_pcond,tdata->_pmutex);//wait释放锁，去等待锁资源队列里排队。等待条件变量满足且有锁可用时，满足后会直接让该线程获取锁(唤醒线程)。
                                    //拿到锁后开始执行_func任务，下次while循环进来继续wait释放锁
        cout<<"================="<<endl;
        cout<<tdata->_name<<endl;
        tdata->_func();
        cout<<"================="<<endl;
        pthread_mutex_unlock(tdata->_pmutex);
    }
    return nullptr;
}

int main()
{
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    pthread_mutex_init(&mutex,nullptr);
    pthread_cond_init(&cond,nullptr);

    pthread_t tids[Num];
    func_t funcs[Num]={func1,func2,func3,func4,func5};
    for(int i=0;i<Num;i++)
    {
        string name="i am thread ";
        name+=to_string(i);
        cout<<i<<endl;
        ThreadData* tdata=new ThreadData(name,&mutex,&cond,funcs[i]);
        pthread_create(&tids[i],nullptr,Entry,(void*)tdata);
    }

    sleep(5);
//1.pthread_cond_signal唤醒锁资源等待队列的第一个线程
    // int cnt=0;
    // while(true)
    // {
    //     sleep(1);
    //     // cout<<"run thread "<<endl;
    //     cnt++;
    //     pthread_cond_signal(&cond);
    // }
//2.pthread_cond_broadcast唤醒资源等待队列的全部线程
    pthread_cond_broadcast(&cond);
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}


